package com.wlit.websocket;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.cors.CorsConfig;
import io.netty.handler.codec.http.cors.CorsConfigBuilder;
import io.netty.handler.codec.http.cors.CorsHandler;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.apache.log4j.Logger;


public class WebSocketServer extends Thread {

    private static Logger logger = Logger.getLogger(WebSocketServer.class);

    private static final int serverPort = 4011;

    public WebSocketServer() {
        super("WebSocketServer");
    }


    public static void doStart() {

        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            //辅助启动工具类
            ServerBootstrap bootstrap = new ServerBootstrap();

            CorsConfig corsConfig = CorsConfigBuilder.forAnyOrigin()
                    .allowNullOrigin()
                    .allowCredentials()
                    .build();

            bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //HttpRequestDecoder和HttpResponseEncoder的一个组合，针对http协议进行编解码
                            pipeline.addLast(new HttpServerCodec());
                            //分块向客户端写数据，防止发送大文件时导致内存溢出
                            pipeline.addLast(new ChunkedWriteHandler());
                            //将HttpMessage和HttpContents聚合到一个完成的 FullHttpRequest或FullHttpResponse中
                            pipeline.addLast(new HttpObjectAggregator(1024 * 1024));
                            //协议处理器
                            pipeline.addLast(new WebSocketServerProtocolHandler("/laberprint"));
                            pipeline.addLast(new CorsHandler(corsConfig));
                            //自定义的处理器
                            WebSocketHandler wsHandler = new WebSocketHandler();
                            pipeline.addLast(wsHandler);
                        }
                    });
            //绑定端口，同步启动
            ChannelFuture future = bootstrap.bind(serverPort).sync();
            logger.info("WebSocket启动成功:" + serverPort);
            System.out.println("WebSocket启动成功:" + serverPort);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.info("WebSocket启动失败:" + e.getMessage());
            System.out.println("WebSocket启动失败:" + e.getMessage());
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    @Override
    public void run() {
        doStart();
    }

}